class Game2048 {
    constructor(gridSize = 4) {
        this.gridSize = gridSize;
        this.grid = [];
        this.score = 0;
        this.highScore = parseInt(localStorage.getItem('highScore')) || 0;
        this.initGame();
        this.setupEventListeners();
    }

    initGame() {
        this.grid = Array(this.gridSize).fill().map(() => 
            Array(this.gridSize).fill(0)
        );
        this.score = 0;
        this.addRandomTile();
        this.addRandomTile();
        this.renderGrid();
        this.updateHighScore();
    }

    updateHighScore() {
        if (this.score > this.highScore) {
            this.highScore = this.score;
            localStorage.setItem('highScore', this.highScore);
        }
        document.getElementById('highScore').textContent = this.highScore;
    }

    addRandomTile() {
        const emptyCells = [];
        for (let r = 0; r < this.gridSize; r++) {
            for (let c = 0; c < this.gridSize; c++) {
                if (this.grid[r][c] === 0) {
                    emptyCells.push({r, c});
                }
            }
        }

        if (emptyCells.length > 0) {
            const {r, c} = emptyCells[Math.floor(Math.random() * emptyCells.length)];
            const value = Math.random() < 0.9 ? 2 : 4;
            this.grid[r][c] = { value: value, isNew: true };
        }
    }

    renderGrid() {
        const gridElement = document.getElementById('grid');
        const scoreElement = document.getElementById('score');
        gridElement.innerHTML = '';
        scoreElement.textContent = this.score;
        this.updateHighScore();

        for (let r = 0; r < this.gridSize; r++) {
            for (let c = 0; c < this.gridSize; c++) {
                const cell = this.grid[r][c];
                const tileElement = document.createElement('div');
                tileElement.classList.add('tile');
                
                if (cell && cell.value) {
                    tileElement.classList.add(`tile-${cell.value}`);
                    tileElement.textContent = cell.value;
                    if (cell.isNew) {
                        tileElement.classList.add('tile-new');
                        delete cell.isNew;
                    }
                    if (cell.merged) {
                        tileElement.classList.add('tile-merge');
                        delete cell.merged;
                    }
                }
                
                gridElement.appendChild(tileElement);
            }
        }
    }

    setupEventListeners() {
        document.addEventListener('keydown', (e) => {
            let moved = false;
            switch(e.key) {
                case 'ArrowUp':
                    moved = this.moveUp();
                    break;
                case 'ArrowDown':
                    moved = this.moveDown();
                    break;
                case 'ArrowLeft':
                    moved = this.moveLeft();
                    break;
                case 'ArrowRight':
                    moved = this.moveRight();
                    break;
            }

            if (moved) {
                this.addRandomTile();
                this.renderGrid();
                this.checkGameStatus();
            }
        });

        document.getElementById('newGame').addEventListener('click', () => {
            this.initGame();
        });
    }

    moveLeft() {
        let moved = false;
        for (let r = 0; r < this.gridSize; r++) {
            const row = this.grid[r];
            const newRow = row.filter(cell => cell && cell.value !== 0);
            
            for (let c = 0; c < newRow.length - 1; c++) {
                if (newRow[c].value === newRow[c + 1].value) {
                    newRow[c].value *= 2;
                    this.score += newRow[c].value;
                    newRow[c].merged = true;
                    newRow.splice(c + 1, 1);
                    moved = true;
                }
            }

            while (newRow.length < this.gridSize) {
                newRow.push(0);
            }

            if (JSON.stringify(row) !== JSON.stringify(newRow)) {
                moved = true;
            }
            this.grid[r] = newRow;
        }
        return moved;
    }

    moveRight() {
        let moved = false;
        for (let r = 0; r < this.gridSize; r++) {
            const row = this.grid[r];
            const newRow = row.filter(cell => cell && cell.value !== 0);
            
            for (let c = newRow.length - 1; c > 0; c--) {
                if (newRow[c].value === newRow[c - 1].value) {
                    newRow[c].value *= 2;
                    this.score += newRow[c].value;
                    newRow[c].merged = true;
                    newRow.splice(c - 1, 1);
                    moved = true;
                }
            }

            while (newRow.length < this.gridSize) {
                newRow.unshift(0);
            }

            if (JSON.stringify(row) !== JSON.stringify(newRow)) {
                moved = true;
            }
            this.grid[r] = newRow;
        }
        return moved;
    }

    moveUp() {
        let moved = false;
        for (let c = 0; c < this.gridSize; c++) {
            const column = this.grid.map(row => row[c]);
            const newColumn = column.filter(cell => cell && cell.value !== 0);
            
            for (let r = 0; r < newColumn.length - 1; r++) {
                if (newColumn[r].value === newColumn[r + 1].value) {
                    newColumn[r].value *= 2;
                    this.score += newColumn[r].value;
                    newColumn[r].merged = true;
                    newColumn.splice(r + 1, 1);
                    moved = true;
                }
            }

            while (newColumn.length < this.gridSize) {
                newColumn.push(0);
            }

            if (JSON.stringify(column) !== JSON.stringify(newColumn)) {
                moved = true;
            }

            for (let r = 0; r < this.gridSize; r++) {
                this.grid[r][c] = newColumn[r];
            }
        }
        return moved;
    }

    moveDown() {
        let moved = false;
        for (let c = 0; c < this.gridSize; c++) {
            const column = this.grid.map(row => row[c]);
            const newColumn = column.filter(cell => cell && cell.value !== 0);
            
            for (let r = newColumn.length - 1; r > 0; r--) {
                if (newColumn[r].value === newColumn[r - 1].value) {
                    newColumn[r].value *= 2;
                    this.score += newColumn[r].value;
                    newColumn[r].merged = true;
                    newColumn.splice(r - 1, 1);
                    moved = true;
                }
            }

            while (newColumn.length < this.gridSize) {
                newColumn.unshift(0);
            }

            if (JSON.stringify(column) !== JSON.stringify(newColumn)) {
                moved = true;
            }

            for (let r = 0; r < this.gridSize; r++) {
                this.grid[r][c] = newColumn[r];
            }
        }
        return moved;
    }

    checkGameStatus() {
        // Check for 2048 win condition
        for (let r = 0; r < this.gridSize; r++) {
            for (let c = 0; c < this.gridSize; c++) {
                if (this.grid[r][c] && this.grid[r][c].value === 2048) {
                    alert('Congratulations! You won!');
                    return;
                }
            }
        }

        // Check for game over (no more moves possible)
        let gameOver = true;
        for (let r = 0; r < this.gridSize; r++) {
            for (let c = 0; c < this.gridSize; c++) {
                if (this.grid[r][c] === 0) {
                    gameOver = false;
                    break;
                }
                
                // Check adjacent cells for possible merges
                if (r < this.gridSize - 1 && this.grid[r][c] && this.grid[r+1][c] && this.grid[r][c].value === this.grid[r+1][c].value) {
                    gameOver = false;
                    break;
                }
                if (c < this.gridSize - 1 && this.grid[r][c] && this.grid[r][c+1] && this.grid[r][c].value === this.grid[r][c+1].value) {
                    gameOver = false;
                    break;
                }
            }
            if (!gameOver) break;
        }

        if (gameOver) {
            alert(`Game Over! Your score: ${this.score}`);
        }
    }
}

// Initialize the game when the page loads
document.addEventListener('DOMContentLoaded', () => {
    new Game2048();
});
